﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Compression;
using System.Runtime.InteropServices;
using AccessDE;
using System.Xml.Linq;
using System.Threading;

namespace BuildDelivery
{
    class Program
    {
        private static string DeliveryDir = @"..\Deliveries";
        private static string DatabaseDir = @"..\MSAccess";
        private static string DeliveryVersion = "";

        static void Main(string[] args)
        {
            if (args.Length != 1)
            {
                Console.WriteLine("Please give a version number in the format '5.0.7'.\nExample: 'BuildDelivery.exe 5.0.8' or 'BuildDelivery.exe 5.0.8'");
                return;
            }

            DatabaseDir = new FileInfo("..\\").Directory.FullName + "\\MSAccess\\";
            DeliveryDir = new FileInfo("..\\").Directory.FullName + "\\Deliveries";
            DeliveryVersion = args[0];


            if (!DeliveryVersion.Contains('.'))
            {
                Console.WriteLine("Please give a version number in the format '5.0.7'.");
                return;
            }


            Console.WriteLine("Copy files...");

            //Then, run the DB clean function on the Acces Data .MDB
            string DBName = DeliveryDir + "\\" + DeliveryVersion + "\\" + "elkatoDaten.mdb";
            string DBName2 = DeliveryDir + "\\" + DeliveryVersion + "\\" + "elkatoAbrechnung.mdb";

            //Normal delivery without SVN
            //First, copy all files into new directory
            CopyFile("elkato.ini");
            CopyFile("elkatoAbrechnung.mdb");
            CopyFile("elkatoDaten.mdb");
            CopyFile("logo.jpg");
            //CopyFile("Release Notes.txt");

            Console.WriteLine("Set version number...");

            //Set version number
            AccessDB.CloseAllAccessProcesses();
            Microsoft.Office.Interop.Access.Application Acc = AccessDB.OpenAccessApplication();
            

            //Source Control off
            Acc.CompactRepair(DBName, DBName + ".tmp");
            Acc.CompactRepair(DBName2, DBName2 + ".tmp");

            File.Delete(DBName);
            File.Delete(DBName2);

            File.Move(DBName + ".tmp", DBName);
            File.Move(DBName2 + ".tmp", DBName2);

            Acc.OpenCurrentDatabase(DBName2, false, null);//open mdb file
            Acc.DoCmd.OpenForm("Main", Microsoft.Office.Interop.Access.AcFormView.acDesign);//, //View    System.Reflection.Missing.Value, //FilterName    System.Reflection.Missing.Value, //WhereCondition    Access.AcFormOpenDataMode.acFormPropertySettings, //DataMode    Access.AcWindowMode.acWindowNormal, //WindowMode    System.Reflection.Missing.Value //OpenArgs    ); 

            Acc.Forms["Main"].Caption = "elkato Abrechnung " + DeliveryVersion;

            AccessDB.CloseAccessApplicationSaveAll();

            Console.WriteLine("Run AusliefernAuto...");

            RunAccessFunction(DBName, "AusliefernAuto");
            RunAccessFunction(DBName2, "AusliefernAuto");
 
            Console.WriteLine("Compile to mde...");
            AccessDB.FullCompileToMDE(new FileInfo(DBName));
            AccessDB.FullCompileToMDE(new FileInfo(DBName2));

            AccessDB.CloseAccessApplicationSaveAll();



            Console.WriteLine("Create second copy...");
            //Now copy everything
            Utility.DirectoryCopy(DeliveryDir + "\\" + DeliveryVersion, DeliveryDir + "\\" + DeliveryVersion + "_Entwickler", true);

            File.Delete(DBName);
            File.Delete(DBName2);

            File.Delete(DeliveryDir + "\\" + DeliveryVersion + "_Entwickler" + "\\" + "elkatoDaten.mde");
            File.Delete(DeliveryDir + "\\" + DeliveryVersion + "_Entwickler" + "\\" + "elkatoAbrechnung.mde");

            Console.WriteLine("Zip files...");

            //Then, ZIP everything
            ZIP();

            
            Console.WriteLine("Create installation package...");

            //Now the Installation package
            string TargetDir = DeliveryDir + "\\" + DeliveryVersion + "_Installer";
            CreatePackage(TargetDir, @"D:\ZAT\CodePlex\MSAccess\elkatoAbrechnung.adepsws");

            Console.WriteLine("Zip installation package...");
            //Then, ZIP everything
            ZipDir(TargetDir, DeliveryDir + "\\elkatoAbrechnung" + DeliveryVersion + "_Installer.zip");

            Console.WriteLine("Finished!");
            Thread.Sleep(1000);
             
        }

        private static void CreatePackage(string TargetDir, string strSettingsPath_)
        {
            string strSettingsPath = strSettingsPath_ + ".tmp";
            CopyFile_(strSettingsPath_, strSettingsPath);

            XElement xe = XElement.Load(strSettingsPath);
            XElement oldnode = xe.Element("OutputOptions").Element("DestinationFolder");
            oldnode.SetValue(TargetDir);
            xe.Save(strSettingsPath);

            AccessDB.CloseAllAccessProcesses();

            //Instantiate a AccessDeveloperExtensions object.
            Microsoft.Office.Interop.Access.Application Acc = AccessDB.OpenAccessApplication();
            AccessDeveloperExtensions objAde = Acc.COMAddIns.Item("AccessAddIn.ADE").Object;

            //Create the deployment package.
            objAde.CreateInstallPackage(strSettingsPath);
            AccessDB.CloseAllAccessProcesses();
            File.Delete(strSettingsPath);
        }

        private static void ZipDir(string Dir, string TargetFilePath)
        {
            FileInfo ZipFile = new FileInfo(TargetFilePath);
            if (ZipFile.Exists)
                ZipFile.Delete();

            System.IO.Compression.ZipFile.CreateFromDirectory(Dir, ZipFile.FullName);
        }

        private static void ZIP()
        {
            string Dir = DeliveryDir + "\\" + DeliveryVersion;

            FileInfo ZipFile = new FileInfo(DeliveryDir + "\\elkatoAbrechnung" + DeliveryVersion + ".zip");
            if (ZipFile.Exists)
                ZipFile.Delete();

            System.IO.Compression.ZipFile.CreateFromDirectory(Dir, ZipFile.FullName);


            Dir = DeliveryDir + "\\" + DeliveryVersion + "_Entwickler";

            ZipFile = new FileInfo(DeliveryDir + "\\elkatoAbrechnung" + DeliveryVersion + "_Entwickler" + ".zip");
            if (ZipFile.Exists)
                ZipFile.Delete();

            System.IO.Compression.ZipFile.CreateFromDirectory(Dir, ZipFile.FullName);
        }

        private static void CopyFile(string NameFrom)
        {
            CopyFile(DatabaseDir, NameFrom);
        }

        private static void CopyFile(string Path, string NameFrom)
        {
            string TargetDir = DeliveryDir + "\\" + DeliveryVersion + "\\";

            if (!Directory.Exists(TargetDir))
                Directory.CreateDirectory(TargetDir);

            File.Copy(Path + NameFrom, TargetDir + NameFrom, true);

            FileAttributes attributes = File.GetAttributes(TargetDir + NameFrom);
            attributes = RemoveAttribute(attributes, FileAttributes.ReadOnly);

            File.SetAttributes(TargetDir + NameFrom, attributes);
        }

        private static void CopyFile_(string From, string To)
        {
            File.Copy(From, To, true);

            FileAttributes attributes = File.GetAttributes(To);
            attributes = RemoveAttribute(attributes, FileAttributes.ReadOnly);

            File.SetAttributes(To, attributes);
        }

        private static FileAttributes RemoveAttribute(FileAttributes attributes, FileAttributes attributesToRemove)
        {
            return attributes & ~attributesToRemove;
        }

        private static void RunAccessFunction(string DBPath, string FunctionName)
        {

            Microsoft.Office.Interop.Access.Application acApp = new Microsoft.Office.Interop.Access.Application();//create msaccess

            acApp.OpenCurrentDatabase(DBPath, false, null);//open mdb file
            acApp.Run(FunctionName);
            acApp.CloseCurrentDatabase();
            acApp.Quit();//exit application
        }
    }
}
